package com.hengyu.oauth2.core;

import com.hengyu.oauth2.entity.HengYuOAuth2ClientToken;
import com.hengyu.oauth2.jpa.HengYuClientTokenJPA;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.ClientKeyGenerator;
import org.springframework.security.oauth2.client.token.ClientTokenServices;
import org.springframework.security.oauth2.client.token.DefaultClientKeyGenerator;
import org.springframework.security.oauth2.client.token.JdbcClientTokenServices;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.SerializationUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;

/**
 * 自定义oauth2查询终端token业务逻辑
 * 项目名称：OAuth2Example
 * 项目版本：V1.0
 * 包名称：com.example.oauth
 * 创建人：yuqy
 * 创建时间：2017/3/16 16:47
 * 修改人：yuqy
 * 修改时间：2017/3/16 16:47
 * 修改备注：
 */
public class HengYuOAuth2ClientTokenService implements ClientTokenServices
{

    private HengYuClientTokenJPA clientTokenDAO;

    public HengYuOAuth2ClientTokenService(HengYuClientTokenJPA clientTokenDAO) {
        this.clientTokenDAO = clientTokenDAO;
    }

    private ClientKeyGenerator keyGenerator = new DefaultClientKeyGenerator();

    private static final Log LOG = LogFactory.getLog(JdbcClientTokenServices.class);

    public void setClientKeyGenerator(ClientKeyGenerator keyGenerator) {
        this.keyGenerator = keyGenerator;
    }

    public OAuth2AccessToken getAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication) {
        OAuth2AccessToken accessToken = null;

        try {
            List<HengYuOAuth2ClientToken> tokens = clientTokenDAO.findAll(new Specification<HengYuOAuth2ClientToken>() {
                @Override
                public Predicate toPredicate(Root<HengYuOAuth2ClientToken> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    criteriaQuery.where(criteriaBuilder.equal(root.get("clientId"),resource.getClientId()));
                    return null;
                }
            });
            accessToken = SerializationUtils.deserialize(tokens.get(0).getToken());
        } catch (EmptyResultDataAccessException var5) {
            if(LOG.isInfoEnabled()) {
                LOG.debug("Failed to find access token for authentication " + authentication);
            }
        }

        return accessToken;
    }

    @Override
    public void saveAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication, OAuth2AccessToken accessToken) {

        this.removeAccessToken(resource, authentication);

        String name = authentication == null?null:authentication.getName();

        HengYuOAuth2ClientToken token = new HengYuOAuth2ClientToken();
        token.setClientId(resource.getClientId());
        token.setTokenId(accessToken.getValue());
        token.setToken(SerializationUtils.serialize(accessToken));
        token.setUserName(name);
        token.setAuthenticationId(keyGenerator.extractKey(resource, authentication));

        clientTokenDAO.save(token);
    }

    @Override
    public void removeAccessToken(OAuth2ProtectedResourceDetails resource, Authentication authentication) {
        HengYuOAuth2ClientToken token = new HengYuOAuth2ClientToken();
        token.setAuthenticationId(keyGenerator.extractKey(resource,authentication));
        clientTokenDAO.delete(token);
    }
}
